﻿using System;

namespace Hsenl.Network {
    public class TcpChannel : Channel {
        private IPacketReceiver _receiver;
        private IPacketSender _sender;
        private IMessageReader _packetReader;
        private IMessageWriter _packetWriter;

        internal override void Init(long channelId) {
            base.Init(channelId);
            this._receiver.Init(this);
            this._sender.Init(this);
            this._packetReader.Init(this);
            this._packetWriter.Init(this);
            this._packetReader.OnMessageReadedEvent += message => { this.OnMessageReaded(this.ChannelId, message); };
            this._packetWriter.OnMessageWritedEvent += message => { this.OnMessageWrited(this.ChannelId, message); };
        }
        
        public void FlushWriter() {
            this._sender.FlushWriter();
        }

        internal override Memory<byte> GetRecvBuffer(int len) {
            return this._receiver.GetRecvBuffer(len);
        }

        internal override Memory<byte> GetSendBuffer(int len) {
            return this._sender.GetSendBuffer(len);
        }

        internal override byte[] GetRecvBuffer(int len, out int offset, out int count) {
            return this._receiver.GetRecvBuffer(len, out offset, out count);
        }

        internal override byte[] GetSendBuffer(int len, out int offset, out int count) {
            return this._sender.GetSendBuffer(len, out offset, out count);
        }

        internal override void Read(Memory<byte> data) {
            try {
                this._packetReader.Read(data);
            }
            catch {
                try {
                    this.OnError(ErrorCode.Error_MessageReadFailure);
                }
                catch (Exception e) {
                    Log.Error(e);
                }

                throw;
            }
        }

        internal override void Write(byte[] data, int offset, int count) {
            try {
                this._packetWriter.Write(data, offset, count);
            }
            catch {
                try {
                    this.OnError(ErrorCode.Error_MessageWriteFailure);
                }
                catch (Exception e) {
                    Log.Error(e);
                }

                throw;
            }
        }

        internal override void Write(Span<byte> data) {
            try {
                this._packetWriter.Write(data);
            }
            catch {
                try {
                    this.OnError(ErrorCode.Error_MessageWriteFailure);
                }
                catch (Exception e) {
                    Log.Error(e);
                }

                throw;
            }
        }

        internal override void Dispose() {
            if (this.IsDisposed)
                return;

            base.Dispose();

            this._receiver.Dispose();
            this._sender.Dispose();
            this._packetReader.Dispose();
            this._packetWriter.Dispose();
        }
    }
}